<template>
  <div class="app-menu-config-wrapper">
    <div class="app-menu-config-left">
      <FList :data-source="formMenus" bordered title-name="menuName" @doubleClick="addAppMenuFromFormMenu">
      </FList>
    </div>
    <div class="app-menu-config-padding"/>
    <div class="app-menu-config-right" v-loading="loading">
      <FPage>
        <template #header>
          <div class="app-menu-config-header">
            <el-button round :icon="Plus" @click="addFolder"
                       :disabled="!(!selectedAppMenu || selectedAppMenu.menuType === 'folder')">添加菜单夹
            </el-button>
            <el-button round :icon="Plus" @click="addTabs"
                       :disabled="!(!selectedAppMenu || selectedAppMenu.menuType === 'folder')">添加页签夹
            </el-button>
            <el-button round :icon="Plus" @click="addComponent"
                       :disabled="!(!selectedAppMenu || selectedAppMenu.menuType === 'folder')">添加自定义菜单
            </el-button>
            <el-button round :icon="Plus" @click="addLink"
                       :disabled="!(!selectedAppMenu || selectedAppMenu.menuType === 'folder')">添加自定义链接
            </el-button>
            <!--        <el-button round type="primary" @click="saveAll">保存所有菜单</el-button>-->
          </div>
        </template>
        <div class="app-menu-config-tree">
          <el-tree show-checkbox node-key="id" ref="appMenuTree"
                   default-expand-all :props="defaultProps"
                   :expand-on-click-node="false" @node-click="selectAppMenu"
                   :check-strictly="true" @check-change="appMenuSelectChange"
                   :data="appMenus">
            <template v-slot="{ node, data }">
              <div class="menu-item">
                <div style="flex: 1">
                  {{ data.menuName }}
                  <span class="menu-type-wrapper">({{ getMenuTypeName(data.menuType) }})</span>
                </div>
                <div style="width: 40px">
                  <el-button v-context="[menuItemContext, data]" size="small" :icon="Setting" circle/>
                </div>
              </div>
            </template>
          </el-tree>
        </div>
      </FPage>
    </div>
<!--    <div class="app-menu-config-padding"/>-->
    <div class="app-menu-config-property" v-show="selectedAppMenu">
      <AppFolderMenuProperty ref="AppFolderMenuProperty" @reload="loadAppMenus"
                             v-show="selectedAppMenu && selectedAppMenu.menuType === 'folder'"/>

      <AppFormMenuProperty ref="AppFormMenuProperty" @reload="loadAppMenus"
                           v-show="selectedAppMenu && selectedAppMenu.menuType === 'formMenu'"/>

      <AppTabsMenuProperty ref="AppTabsMenuProperty" @reload="loadAppMenus"
                           v-show="selectedAppMenu && selectedAppMenu.menuType === 'tabs'"/>

      <AppComponentMenuProperty ref="AppComponentMenuProperty" @reload="loadAppMenus"
                                v-show="selectedAppMenu && selectedAppMenu.menuType === 'component'"/>

      <AppLinkMenuProperty ref="AppLinkMenuProperty" @reload="loadAppMenus"
                           v-show="selectedAppMenu && selectedAppMenu.menuType === 'link'"/>

      <FlowMenuProperty ref="FlowMenuProperty" @reload="loadAppMenus"
                        v-show="selectedAppMenu && selectedAppMenu.menuType === 'flow'"/>

      <FlowListProperty ref="FlowListProperty" @reload="loadAppMenus"
                        v-show="selectedAppMenu && selectedAppMenu.menuType === 'flowList'"/>
    </div>

    <AppFolderMenuConfig ref="AppFolderMenuConfig" @addFolder="doAddFolder"/>
    <AppTabsMenuConfig ref="AppTabsMenuConfig" @addTabs="doAddTabs"/>
    <AppComponentMenuConfig ref="AppComponentMenuConfig" @addComponentMenu="doAddTabs"/>
    <AppLinkMenuConfig ref="AppLinkMenuConfig" @addLink="doAddTabs"/>
  </div>
</template>

<script>
import FList from '@/components/FList';
import {deleteAction, getAction, postAction} from '@/request/BaseRequest';
import {findItemFromTrees, findListTitle, guid, isEmpty, listToTrees, treesToList} from '@/utils/CommonUtils';
import {Plus, Setting} from '@element-plus/icons-vue';
import AppFolderMenuConfig from '@/components/app/AppFolderMenuConfig';
import {DefaultAppMenuDefinition} from '@/components/form/DefaultFormDefinition';
import {ElMessageBox} from 'element-plus';
import AppFolderMenuProperty from '@/components/app/menus/AppFolderMenuProperty.vue';
import AppFormMenuProperty from '@/components/app/menus/AppFormMenuProperty.vue';
import AppTabsMenuProperty from '@/components/app/menus/AppTabsMenuProperty.vue';
import AppTabsMenuConfig from '@/components/app/AppTabsMenuConfig.vue';
import AppComponentMenuConfig from '@/components/app/AppComponentMenuConfig.vue';
import AppComponentMenuProperty from '@/components/app/menus/AppComponentMenuProperty.vue';
import AppLinkMenuConfig from '@/components/app/AppLinkMenuConfig.vue';
import AppLinkMenuProperty from '@/components/app/menus/AppLinkMenuProperty.vue';
import {markRaw} from 'vue';
import FlowMenuProperty from '@/components/app/menus/FlowMenuProperty';
import MenuFactory from '@/components/app/menus/MenuFactory';
import FlowListProperty from '@/components/app/menus/FlowListProperty.vue';
import FPage from '@/components/layout/FPage.vue';

export default {
  name: "AppMenuConfig",
  components: {
    FPage,
    FList,
    FlowMenuProperty,
    AppFolderMenuConfig,
    AppFormMenuProperty,
    AppTabsMenuConfig,
    AppTabsMenuProperty,
    AppComponentMenuConfig,
    AppComponentMenuProperty,
    AppLinkMenuConfig,
    AppLinkMenuProperty,
    FlowListProperty,
    AppFolderMenuProperty
  },
  data() {
    return {
      loading: false,
      Plus: markRaw(Plus),
      Setting: markRaw(Setting),
      formMenus: [],
      appMenus: [],
      menuType: [{id: 'link', title: '链接'},
        {id: 'formMenu', title: '表单'},
        {id: 'tabs', title: '页签夹'},
        {id: 'component', title: '自定义菜单'},
        {id: 'flow', title: '流程'},
        {id: 'flowList', title: '流程列表'},
        {id: 'folder', title: '菜单夹'}],
      defaultProps: {
        children: 'children',
        label: 'menuName',
      },
      filterText: undefined,
      selectedAppMenu: undefined,
      selectedAppMenuKey: undefined,
      menuFactory: new MenuFactory(),
      menuItemContext: {
        width: 100,
        context: [
          {title: '上移', id: 'upAppMenu'},
          {title: '下移', id: 'downAppMenu'},
          {title: '删除', id: 'deleteAppMenu'},
        ],
        click: this.menuItemContextClick,
        close: () => null,
      }
    };
  },
  methods: {
    active() {
      this.loadFormMenus();
      this.loadAppMenus();
    },
    loadAppMenus() {
      this.loading = true;
      getAction('/plat/platAppMenu/query', {_order: 'asc', _orderBy: 'sort'}).then(data => {
        if (data.success) {
          this.resolveAppMenus(data.result);
        } else {
          this.$notification.error({message: data.message, result: data.result, duration: 3});
        }
        this.loading = false;
      });
    },
    resolveAppMenus(list) {
      if (!list) list = [];
      this.appMenus = listToTrees(list);
    },
    selectAppMenu(node) {
      this.$nextTick(() => {
        if (this.selectedAppMenuKey === node.id) {
          this.$refs.appMenuTree.setCheckedKeys([]);
          this.clearSelectedKeys();
        } else {
          this.setSelectedMenuKey(node.id);
        }
      });
    },
    appMenuSelectChange() {
      let checkedKeys = this.$refs.appMenuTree.getCheckedKeys();
      if (!checkedKeys || checkedKeys.length <= 0) {
        this.clearSelectedKeys();
      } else if (checkedKeys.length === 1) {
        this.setSelectedMenuKey(checkedKeys[0]);
      } else {
        for (let i = 0; i < checkedKeys.length; i++) {
          if (checkedKeys[i] !== this.selectedAppMenuKey) {
            this.setSelectedMenuKey(checkedKeys[i]);
            return;
          }
        }
        this.clearSelectedKeys();
      }
    },
    clearSelectedKeys() {
      this.selectedAppMenuKey = undefined;
      this.selectedAppMenu = undefined;
    },
    setSelectedMenuKey(key) {
      this.$nextTick(() => {
        this.$refs.appMenuTree.setCheckedKeys([key]);
        this.selectedAppMenuKey = key;
        this.selectedAppMenu = findItemFromTrees(this.appMenus, this.selectedAppMenuKey);
        this.editMenu();
      });
    },
    editMenu() {
      if (!this.selectedAppMenu) return;
      if (this.selectedAppMenu.menuType === 'folder') {
        this.$nextTick(() => {
          this.$refs.AppFolderMenuProperty.setData(this.selectedAppMenu);
        });
      }

      if (this.selectedAppMenu.menuType === 'formMenu') {
        this.$nextTick(() => {
          this.$refs.AppFormMenuProperty.setData(this.selectedAppMenu);
        });
      }

      if (this.selectedAppMenu.menuType === 'tabs') {
        this.$nextTick(() => {
          this.$refs.AppTabsMenuProperty.setData(this.selectedAppMenu);
        });
      }

      if (this.selectedAppMenu.menuType === 'component') {
        this.$nextTick(() => {
          this.$refs.AppComponentMenuProperty.setData(this.selectedAppMenu);
        });
      }

      if (this.selectedAppMenu.menuType === 'link') {
        this.$nextTick(() => {
          this.$refs.AppLinkMenuProperty.setData(this.selectedAppMenu);
        });
      }

      if (this.selectedAppMenu.menuType === 'flow') {
        this.$nextTick(() => {
          this.$refs.FlowMenuProperty.setData(this.selectedAppMenu);
        });
      }

      if (this.selectedAppMenu.menuType === 'flowList') {
        this.$nextTick(() => {
          this.$refs.FlowListProperty.setData(this.selectedAppMenu);
        });
      }
    },
    loadFormMenus() {
      let appId = this.$route.query.appId;
      this.loading = true;
      getAction('/plat/loadFormMenus', {appId}).then(data => {
        this.loading = false;
        if (data.success) {
          this.resolveFormMenus(data.result);
          this.loadFlowsByAppId(appId);
        }
      });
    },
    resolveFormMenus(result) {
      if(isEmpty(result)) result = [];
      for (let i = 0; i < result.length; i++) {
        result[i].menuType = 'formMenu'
      }
      this.formMenus = result
    },
    loadFlowsByAppId(appId) {
      this.loading = true;
      getAction('/plat/loadFlowByAppId', {appId}).then(data => {
        this.loading = false;
        if (data.success) {
          let result = data.result;
          this.resolveFlowMenus(result);
        }
      });
    },
    resolveFlowMenus(flows) {
      let res = [];
      if (isEmpty(flows)) return;
      flows.forEach(flow => {
        res.push({
          id: guid(),
          menuType: 'flow',
          component: 'views/FlowWork/List',
          menuName: `${flow.name}`,
          flowId: flow.id
        });
      });
      this.formMenus.push(...res);
    },
    doAddTabs(folder) {
      if (!this.selectedAppMenuKey) {
        this.appMenus.push(folder);
      } else {
        let appMenu = findItemFromTrees(this.appMenus, this.selectedAppMenuKey);
        if (appMenu) {
          if (!appMenu.children) appMenu.children = [];
          folder.parentId = appMenu.id;
          appMenu.children.push(folder);
        }
      }
      this.saveAll();
    },
    doAddFolder(folder) {
      folder.path = '/' + folder.id;
      if (!this.selectedAppMenuKey) {
        this.appMenus.push(folder);
      } else {
        let appMenu = findItemFromTrees(this.appMenus, this.selectedAppMenuKey);
        if (appMenu) {
          if (!appMenu.children) appMenu.children = [];
          folder.parentId = appMenu.id;
          appMenu.children.push(folder);
        }
      }
      this.saveAll();
    },
    addLink() {
      let appMenus = this.menuFactory.createMenus({menuType: 'link'}, this.$route.query.appId);
      this.$refs.AppLinkMenuConfig.setData(appMenus);
    },
    addComponent() {
      this.$refs.AppComponentMenuConfig.setData(JSON.parse(JSON.stringify(DefaultAppMenuDefinition)));
    },
    addTabs() {
      this.$refs.AppTabsMenuConfig.setData(JSON.parse(JSON.stringify(DefaultAppMenuDefinition)));
    },
    addFolder() {
      this.$refs.AppFolderMenuConfig.setData(JSON.parse(JSON.stringify(DefaultAppMenuDefinition)));
    },
    menuItemContextClick(item, menuItem) {
      if (item.id === 'deleteAppMenu') {
        this.deleteMenu(item, menuItem);
      }
    },
    getMenuTypeName(id) {
      return findListTitle(id, this.menuType);
    },
    deleteMenu(item, menuItem) {
      this.menuItemContext.close();
      ElMessageBox.confirm('删除后不可恢复, 确定删除吗', {
        draggable: true,
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).then(() => {
        this.doDeleteMenu(menuItem);
        this.clearSelectedKeys();
      }).catch(() => {
      });
    },
    doDeleteMenu(item) {
      this.loading = true;
      deleteAction('/plat/platAppMenu/remove', {id: item.id}).then(data => {
        if (data.success) {
          this.loadAppMenus();
        } else {
          this.$notification.error({message: data.message, duration: 3});
        }
        this.loading = false;
      });
    },
    saveAll() {
      let list = treesToList(this.appMenus);
      if (!list || list.length <= 0) {
        this.$message.warning('请添加菜单');
        return;
      }
      for (let i = 0; i < list.length; i++) {
        list[i].appId = this.$route.query.appId;
      }
      this.loading = true;
      postAction('/plat/platAppMenu/updateUnitMenusAll', list).then(data => {
        if (data.success) {
          this.$message.success('操作成功');
        } else {
          this.$notification.error({message: data.message, duration: 3});
        }
        this.loading = false;
      });
    },
    addAppMenuFromFormMenu(formMenuItem) {
      let appMenus = this.menuFactory.createMenus(formMenuItem, this.$route.query.appId);
      if (!appMenus) {

      }
      if (this.selectedAppMenu) {
        if (this.isFolder(this.selectedAppMenu) || this.isTab(this.selectedAppMenu)) {
          appMenus.forEach(menu => {
            menu.parentId = this.selectedAppMenu.id;
          });
          if (!this.selectedAppMenu.children) {
            this.selectedAppMenu.children = [];
          }
          this.selectedAppMenu.children.push(...appMenus);
        } else {
          this.$message.warning('不能放在这个菜单下面');
          return;
        }
      } else {
        this.appMenus.push(...appMenus);
      }
      this.saveAll();
    },
    isTab(menu) {
      if (menu && menu.menuType && menu.menuType === 'tabs') {
        return true;
      }
      return false;
    },
    isFolder(menu) {
      if (menu && menu.menuType && menu.menuType === 'folder') {
        return true;
      }
      return false;
    },
  },
  watch: {
    filterText(val) {
      this.$refs.treeRef.filter(val);
    },
  }
};
</script>

<style scoped>
.app-menu-config-wrapper {
  background: #f4f4f5;
  height: calc(100VH - 39px);
  box-sizing: border-box;
  //padding-top: 10px;
  display: flex;
}

.app-menu-config-left {
  width: 260px;
  background: white;
  height: 100%;
  overflow: auto;
}

.app-menu-config-padding {
  width: 10px;
}

.app-menu-config-right {
  flex: 1;
  height: 100%;
  background: white;
  overflow: auto;
}

.app-menu-config-header {
  height: 40px;
  border: 1px solid rgb(220, 223, 230);
  display: flex;
  align-items: center;
  padding-left: 10px;
  position: sticky;
  top: 0;
  background: white;
}

.app-menu-config-property {
  width: 400px;
  background: white;
  border: 1px solid rgb(220, 223, 230);
}

.menu-item {
  height: 40px;
  padding-left: 20px;
  display: flex;
  align-items: center;
  box-sizing: border-box;
  font-size: 16px;
  flex: 1;
}
</style>

<style>
.app-menu-config-tree {
  background: white;
  height: 100%;
}
.app-menu-config-tree .el-tree-node__content {
  height: 40px;
  border-width: 1px;
  border-style: solid;
  border-color: rgba(255, 255, 255, 0);
}

.app-menu-config-tree .el-tree-node {
}

.app-menu-config-tree .el-tree-node__content:hover {
  border-color: rgb(24, 174, 255);
  background: none;
}

.app-menu-config-tree .el-tree {
  --el-tree-node-hover-bg-color: none;
}

.menu-type-wrapper {
  color: #A8ABB2;
  margin-left: 10px;
  font-style: italic;
  font-size: 12px;
}
</style>
